package com.deimos.sps;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import org.apache.axiom.om.OMElement;
import org.vast.cdm.common.DataComponent;
import org.vast.ows.OWSException;
import org.vast.ows.sps.DescribeTaskingResponse;
import org.vast.ows.sps.SPSUtils;
import org.vast.ows.sps.StatusReport;
import org.vast.ows.sps.TaskingRequest;
import org.vast.ows.sps.UpdateRequest;
import org.vast.ows.sps.UpdateResponse;
import org.vast.ows.sps.StatusReport.RequestStatus;
import org.vast.ows.sps.StatusReport.TaskStatus;
import org.vast.sweCommon.SWEData;
import org.vast.util.DateTime;
import org.vast.xml.DOMHelper;
import org.w3c.dom.Element;
import com.deimos.UtilsDeimos;
import com.deimos.dataBase.Event;
import com.deimos.dataBase.Sensor;
import com.deimos.dataBase.Task;

public class Update extends GetFeasibility {
    private UpdateResponse response;
    SWEData requestParameters;
    SWEData currentParameters;
    Event event;
    SWEData newParameters = new SWEData();
    OMElement update = null;

    String task = null;

    public Update(UpdateRequest request, Sensor sensor, OMElement update) throws Exception {
	super();

	this.update = update;
	event = taskController.getLastEvent(request.getTaskID());

	if (event == null)
	    throw new OWSException(OWSException.invalid_param_code, "task not found", request.getTaskID(), "The information was not found in the data base");

	this.sensor = sensor;

	taskController.validateStatus(event.getTask().getTaskId());
	if (event.getTaskStatus() == TaskStatus.InExecution || (event.getTaskStatus() == null && event.getRequestStatus() == RequestStatus.Accepted) || event.getTaskStatus() == TaskStatus.Reserved) {
	    try {
		this.currentParameters = readParams(event.getRequestParameters());
	    } catch (Exception ex) {
		ex.printStackTrace();
		taskController.removeEvent(event);
		allowGetFeasibility = false;
		return;
	    }
	    this.requestParameters = request.getParameters();
	    saveParameters(this.requestParameters.getDataComponents(), this.currentParameters.getDataComponents());
	    this.init(request, request.getTaskID(), Operation.UPDATED, sensor, null);
	} else {
	    this.init(request, request.getTaskID(), Operation.UPDATED, sensor, null);
	    allowGetFeasibility = false;
	    return;
	}

	/*task = taskController.isSensorInUse(request.getSensorID(), begin, end);
	if (task != null && task.compareTo(request.getTaskID()) != 0) {
	    allowGetFeasibility = false;
	}*/

    }

    public UpdateResponse getResponse() throws OWSException {
	response = (UpdateResponse) super.getResponse();
	if (!allowGetFeasibility) {
	    /*if (task != null) {
		response.getReport().setDescription("The sensor " + response.getReport().getSensorID() + " is in use by the task " + task);
	    } else {*/
		response.getReport().setDescription("The task can not be updated because the task status is not correct.");
	    //}
	    response.getReport().setRequestStatus(RequestStatus.Rejected);
	} else if (response.getReport().getRequestStatus() == RequestStatus.Accepted) {
	    response.getReport().setTaskID(this.updateTask);
	    response.getReport().setDescription("Task updated successfully. " + percentage);
	    insertEvent();
	} else if (response.getReport().getRequestStatus() == RequestStatus.Rejected) {
	    response.getReport().setTaskID(this.updateTask);
	} else if (response.getReport().getRequestStatus() == RequestStatus.Pending) {
	    insertEvent();
	}

	return response;
    }

    public void insertEvent() {
	Event event = new Event();
	StatusReport report = response.getReport();
	event.setRequestStatus(report.getRequestStatus());
	event.setTaskStatus(this.event.getTaskStatus());
	event.setDescription(report.getDescription());
	event.setUpdateDate(new DateTime());
	event.setEstimatedToC(report.getEstimatedToC());

	event.setFeasibilityStudy(report != null && report.getRequestStatus() == RequestStatus.Accepted);
	event.setBeginDate(begin);
	event.setEndDate(end);

	event.setEstimatedToC(response.getReport().getEstimatedToC());
	event.setResponseParameters(UtilsDeimos.getParameters(response));
	event.setRequestParameters(UtilsDeimos.getParameters(request));
	event.setUpdateDate(new DateTime());
	event.setEventId(null);
	event.setBeginDate(begin);
	event.setEndDate(end);
	if (report.getRequestStatus() == RequestStatus.Accepted || report.getRequestStatus() == RequestStatus.Rejected) {
	    // Syn
	    event.setTask(this.event.getTask());
	    event.setOperation(this.event.getOperation());
	    System.out.print("Insert Event " + event.getTask().getTaskId() + " " + this.event.getEventId() + " " + event.getRequestStatus() + " " + event.getDescription());
	    taskController.insertEvent(event);
	    this.event.getTask().setSegments(segments);
	    taskController.insertTask(this.event.getTask());
	} else {
	    // ASyn
	    Task task = new Task();
	    task.setSensorId(request.getSensorID());
	    task.setServiceType(response.getService());
	    task.setTaskId(report.getTaskID());
	    task.setTitle(report.getTitle());
	    event.setOperation(Operation.UPDATED);
	    // event.setTaskStatus(TaskStatus..TASK_UPDATED);
	    task.addEvent(event);
	    task.setSegments(segments);
	    taskController.insertTask(task);
	}

    }

    private SWEData readParams(String params) throws Exception {
	if (params == null)
	    return null;

	SPSUtils utils = new SPSUtils();

	// parse params
	InputStream is = new ByteArrayInputStream(params.getBytes("UTF-8"));
	DOMHelper peticion = new DOMHelper(is, false);

	// read describe tasking response
	String taskURL = sensor.getDescribeTasking();
	DOMHelper domTask = new DOMHelper(taskURL, false);
	DescribeTaskingResponse dtResponse = utils.readDescribeTaskingResponse(domTask.getRootElement());

	// Get Tasking parameters description
	DataComponent taskingParams = dtResponse.getTaskingParameters();

	Element elt = peticion.getBaseElement();
	DOMHelper domRequest = new DOMHelper(elt.getOwnerDocument());
	TaskingRequest request = (TaskingRequest) utils.readParameterizedRequest(domRequest, domRequest.getRootElement(), taskingParams);

	return request.getParameters();
    }

    private void saveParameters(DataComponent requestComponent, DataComponent currentComponent) {
	for (int i = 0; i < requestComponent.getComponentCount(); i++) {
	    if (requestComponent.getComponent(i).getProperty("updatable") != null && requestComponent.getComponent(i).getProperty("updatable").equals(true)) {
		replaceComponent(requestComponent.getComponent(i), currentComponent);
	    }
	    saveParameters(requestComponent.getComponent(i), currentComponent);
	}
    }

    private DataComponent replaceComponent(DataComponent requestComponent, DataComponent currentComponent) {
	for (int i = 0; i < currentComponent.getComponentCount(); i++) {
	    if (currentComponent.getComponent(i).getName().compareTo(requestComponent.getName()) == 0) {
		currentComponent.getComponent(i).setData(requestComponent.getData().copy());
		return null;
	    } else {
		replaceComponent(currentComponent.getComponent(i), currentComponent);
	    }
	}
	return null;
    }
}